package com.tca.cloud.standalone.config;

import com.tca.cloud.standalone.config.mvc.HttpServletRequestStandalone;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * jdk动态代理
 * @author zhouan
 */
public class FeignProxyHandler<T> implements InvocationHandler {

    private Class<T> clazz;

    private BeanFactory beanFactory;

    private String prefix;

    private RequestMappingHandlerMapping handlerMapping;

    public FeignProxyHandler(Class clazz, BeanFactory beanFactory, String prefix) {
        this.clazz = clazz;
        this.beanFactory = beanFactory;
        this.prefix = prefix;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (handlerMapping == null) {
            synchronized (this) {
                if (handlerMapping == null) {
                    // 直接用beanName == requestMappingHandlerMapping, 根据类型取
                    // 当第三方jar同时引用springmvc和springsecurity时, springsecurity也提供了一个 RequestMappingHandlerMapping,
                    // 这里我们需要使用springmvc内置的即可
                    handlerMapping = (RequestMappingHandlerMapping) beanFactory.getBean("requestMappingHandlerMapping");
//                    handlerMapping = (RequestMappingHandlerMapping) beanFactory.getBean("oauth2EndpointHandlerMapping");
//                    handlerMapping = beanFactory.getBean(RequestMappingHandlerMapping.class);
                }
            }
        }

        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        // 获取RequestMapping相关属性, 使用 AnnotatedElementUtils#findMergedAnnotation 方法, 可以获取到GetMapping、PostMapping等
        RequestMapping methodMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
        String path = prefix + methodMapping.value()[0];
        RequestMethod[] requestMethods = methodMapping.method();
        String methodType = requestMethods.length == 0? "": requestMethods[0].name();
        // 组装HttpServletRequest, 通过HttpServletRequest获取对应的HandlerMethod!!!
        HandlerExecutionChain handler = this.handlerMapping.getHandler(new HttpServletRequestStandalone(path, methodType));
        HandlerMethod handlerMethod = (HandlerMethod) handler.getHandler();
        return handlerMethod.getMethod().invoke(handlerMethod.getBean(), args);
    }



}